package com.sinodata.bsm.center.service.resource;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.sinodata.bsm.center.cache.ResCache;
import com.sinodata.bsm.center.cache.ResPauseRuleCache;
import com.sinodata.bsm.center.dao.BaseDao;
import com.sinodata.bsm.center.dao.impl.ResDaoImpl;
import com.sinodata.bsm.common.constants.ResConstants;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResPauseRule;
import com.sinodata.bsm.center.message.ProbeMessenger;

@Service
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ResPauseService {
    private static Logger logger = Logger.getLogger(ResPauseService.class);
    @Autowired
    private BaseDao baseDao;
    @Autowired
    private ResPauseRuleCache resPauseRuleCache;
    @Autowired
    private ResCache resCache;
    @Autowired
    private ResDaoImpl resDaoImpl;

    @Transactional(propagation = Propagation.REQUIRED)
    public void saveOrUpdateResPauseRule(ResPauseRule rule) {
        baseDao.saveOrUpdate(rule);
        resPauseRuleCache.put(rule.getResId(), rule);
    }

    public List<ResPauseRule> findRuleByResId(Long resId) {
        return resPauseRuleCache.getByResId(resId);
    }

    public ResPauseRule findById(Long id) {
        return resPauseRuleCache.get(id);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteResPauseRule(Long id) {
        baseDao.delete(findById(id));
        resPauseRuleCache.remove(id);
    }

    /**
     * 获取已设置暂停规则的资源Id
     * 
     * @return
     */
    public Set<Long> getPausedRuleResIds() {
        return resPauseRuleCache.getPausedResIds();
    }

    /**
     * 获取资源表中所有已暂停的资源
     * 
     * @return
     */
    public Set<Long> findAllPausedResIds() {
        return resDaoImpl.findPausedResIds();
    }

    /**
     * 
     * @param res
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void setResPaused(Res res) {
        res.setPaused(ResConstants.RES_PAUSED);
        resCache.put(res.getId().longValue(), res);
        baseDao.update(res);
        ProbeMessenger.notifyResPaused(res);
    }

    /**
     * 恢复资源暂停状态，即变为正常状态
     * 
     * @param res
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void resumeResPaused(Res res) {
        res.setPaused(ResConstants.RES_NOT_PAUSED);
        resCache.put(res.getId().longValue(), res);
        baseDao.update(res);
        ProbeMessenger.notifyResResume(res);
    }

    /**
     * 查看资源当前是否为暂停状态
     * 
     * @param resId
     * @return
     */
    public ResPauseRule currentPausedResRule(Long resId) {
        List<ResPauseRule> list = findRuleByResId(resId);
        if (list != null) {
            for (ResPauseRule rule : list) {
                if (rule.getStatus() != 0 && isPausedCurrently(rule)) {
                    return rule;
                }
            }
        }
        return null;
    }

    public boolean isPausedCurrently(ResPauseRule rule) {
        if (rule.getStatus() == 0) {
            return false;
        }
        if (rule.getType() == ResConstants.RES_PAUSE_TYPE_ALL) {
            return true;
        } else if (rule.getType() == ResConstants.RES_PAUSE_TYPE_TIM) {
            String expr = rule.getRule();
            String[] times = expr.split("@");
            if (times.length == 1) {
                long time = Long.parseLong(times[0]);
                if (time <= System.currentTimeMillis()) {
                    return true;
                }
            } else if (times.length == 2) {
                long start = Long.parseLong(times[0]);
                long end = Long.parseLong(times[1]);
                if (start <= System.currentTimeMillis() && end > System.currentTimeMillis()) {
                    return true;
                }
            }
        } else if (rule.getType() == ResConstants.RES_PAUSE_TYPE_CYC) {
            String expr = rule.getRule();
            String[] times = expr.split("@");
            if (times.length != 2) {
                return false;
            }
            CronExpression cron;
            try {
                cron = new CronExpression(times[0]);
            } catch (ParseException e) {
                logger.error("解析表cron达式错误:" + expr, e);
                return false;
            }
            long time = System.currentTimeMillis() - Long.parseLong(times[1]) * 1000;
            Date date = cron.getNextValidTimeAfter(new Date(time));
            if (date.getTime() < System.currentTimeMillis()) {
                return true;
            }
        }
        return false;
    }

}
